package com.tidc.seaserverservice.service.impl;

import com.alibaba.fastjson.JSONObject;
import com.fasterxml.jackson.databind.ObjectMapper;
import com.tidc.seaservermapper.dao.RabbitMessageLogDao;
import com.tidc.seaservermapper.dao.TaskDao;
import com.tidc.seaservermapper.dao.UserDao;
import com.tidc.seaservermapper.dao.UserTaskDao;
import com.tidc.seaservermodel.config.RabbitConfig;
import com.tidc.seaservermodel.dto.TaskDto;
import com.tidc.seaservermodel.dto.UserDto;
import com.tidc.seaservermodel.entity.*;
import com.tidc.seaservermodel.exception.TidcAuthorityException;
import com.tidc.seaservermodel.exception.TidcBadParent;
import com.tidc.seaservermodel.exception.TidcQuartzException;
import com.tidc.seaservermodel.properties.QuartzProperties;
import com.tidc.seaservermodel.util.SerializeUtil;
import com.tidc.seaservermodel.util.SpringUtil;
import com.tidc.seaserverservice.service.SecondaryTaskService;
import com.tidc.seaserverservice.util.LogUtil;
import com.tidc.seaserverservice.util.RabbitUtil;
import com.tidc.seaserverservice.util.StringUtil;
import com.tidc.seaserverservice.util.UserUtil;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang3.StringUtils;
import org.springframework.amqp.rabbit.connection.CorrelationData;
import org.springframework.amqp.rabbit.core.RabbitTemplate;
import org.springframework.http.HttpEntity;
import org.springframework.http.HttpHeaders;
import org.springframework.http.MediaType;
import org.springframework.security.core.Authentication;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.util.LinkedMultiValueMap;
import org.springframework.util.MultiValueMap;
import org.springframework.web.client.RestTemplate;

import javax.annotation.Resource;
import java.sql.SQLException;
import java.sql.Timestamp;
import java.text.ParseException;
import java.text.SimpleDateFormat;
import java.util.ArrayList;
import java.util.Date;
import java.util.List;
import java.util.Map;

/**
 * @author ：冯涛滔
 * @date ：Created in 2020/9/14 16:25
 * @description：
 * @modified By：
 * @version:
 */
@Service
@Slf4j
public class SecondaryTaskServiceImpl implements SecondaryTaskService {
    @Resource
    private UserUtil userUtil;
    @Resource
    private UserDao userDao;
    @Resource
    private TaskDao taskDao;
    @Resource
    private UserTaskDao userTaskDao;
    @Resource
    private QuartzProperties quartzProperties;
    @Resource
    private RestTemplate restTemplate;
    @Resource
    private ObjectMapper objectMapper;
    @Resource
    private RabbitMessageLogDao rabbitMessageLogDao;
    @Resource
    private RabbitUtil rabbitUtil;
    @Override
    public Fres<Map<Object, Object>> getTaskAll(String query,int pageSize, int pageNum, Authentication authentication) throws TidcBadParent, ParseException {
        UserDto user = userDao.getUserInfo(Integer.parseInt(authentication.getName()));
        List<TaskDto> res = new ArrayList<>();
        int count = taskDao.getUserTaskCount(query,user.getUser().getSuperiorUserId());
        Map<Object, Object> map = SpringUtil.pagingPrepare(pageSize, pageNum, count);
        List<Task> tasks  = userTaskDao.secondaryQueryAllByLimit(query,(pageNum - 1) * pageSize, pageSize, user.getUser().getId(), user.getUser().getSuperiorUserId());


        for (Task task : tasks) {
//            一次性任务
            if (checkReceive(task.getTypeClassify(), task.getReceiveCreateTime(), task.getReceiveFinishTime()) && user.getLevelNum() >= task.getPrepositionLevel()) {
                res.add(new TaskDto(task, 0));
                continue;
            }
            //不给接
            res.add(new TaskDto(task, 1));
        }
        map.put("list", res);
        return Fres.Success(map, "查询成功");
    }

    @Transactional(rollbackFor = {TidcBadParent.class, ParseException.class, SQLException.class, TidcAuthorityException.class})
    @Override
    public Fres<String> receiveTask(Task task, Authentication authentication) throws TidcBadParent, ParseException, SQLException, TidcAuthorityException, TidcQuartzException {
        User user = userUtil.getUser(authentication);
        //要确认这个任务的主人是上级
        Task checkTask = taskDao.queryById(task.getId());
        if (checkTask == null || !checkTask.getUserId().equals(user.getSuperiorUserId())) {
            log.warn("参数错误具体参数 checkTask {} ,userSuperiorId {}", checkTask, user.getSuperiorUserId());
            throw new TidcBadParent("参数错误请求拒绝");
        }
        UserTask checkTime = userTaskDao.queryByUserIdAndTaskId(Integer.parseInt(authentication.getName()), task.getId());
        if (checkTime != null) {
            if (!checkReceive(checkTask.getTypeClassify(), checkTime.getCreateTime(), checkTime.getFinishTime())) {
                log.warn("id为 {} 的用户视图重复接取 id为 {} 的任务 被拒绝", user.getId(), task.getId());
                throw new TidcBadParent("不能重复接取这个任务");
            }
        }
        //判断是否满足条件
        int prepositionLevel = userTaskDao.checkPrepositionLevel(task.getId());
        if (user.getLevelValue() < prepositionLevel) {
            throw new TidcAuthorityException("等级不足以接取这个任务");
        }
        //接取
        UserTask userTask = new UserTask();
        userTask.setUserId(Integer.parseInt(authentication.getName())).setTaskId(task.getId());
        userTaskDao.receiveTask(userTask);
        if (checkTask.getLimitTime() != null && checkTask.getLimitTime() > 0) {
            JSONObject json = new JSONObject();
            json.put("id", userTask.getId());
            json.put("taskId", userTask.getTaskId());
            json.put("limitTime", checkTask.getLimitTime());
            json.put("limitDate", checkTask.getLimitDate());
            HttpHeaders headers = new HttpHeaders();
            headers.setContentType(MediaType.APPLICATION_JSON_UTF8);
            headers.add("organization", "TIDC");
            HttpEntity<String> req = new HttpEntity(json.toString(), headers);
            Fres response = restTemplate.postForObject(quartzProperties.getUrl() + quartzProperties.getAddTaskCountDown()
                    , req, Fres.class);
            if (response == null || response.getMeta().getStatus() != 200) {
                throw new TidcQuartzException("创建任务倒计时失败");
            }
        }
        return Fres.Success();
    }

    @Override
    public Fres<Map<Object, Object>> getIReceiveTask(int pageSize, int pageNum, Authentication authentication) throws TidcBadParent {
        int taskCount = userTaskDao.getITaskCount(Integer.parseInt(authentication.getName()));
        Map<Object, Object> map = SpringUtil.pagingPrepare(pageSize, pageNum, taskCount);
        List<Task> iReceiveTask = userTaskDao.getIReceiveTask((pageNum - 1) * pageSize, pageSize, Integer.parseInt(authentication.getName()));
        map.put("list", iReceiveTask);
        return Fres.Success(map, "查询成功");
    }

    @Override
    public Fres<Map<Object, Object>> getOngoingTask(int pageSize, int pageNum, Authentication authentication) throws TidcBadParent {
        int count = userTaskDao.getSecondaryOngoingTaskCount(Integer.parseInt(authentication.getName()));
        Map<Object, Object> map = SpringUtil.pagingPrepare(pageSize, pageNum, count);
        List<Task> list = userTaskDao.getSecondaryOngoingTaskList((pageNum - 1) * pageSize, pageSize, Integer.parseInt(authentication.getName()));
        map.put("list", list);
        return Fres.Success(map, "成功");
    }

    @Transactional(rollbackFor = {TidcBadParent.class, SQLException.class})
    @Override
    public Fres<String> finishTask(Authentication authentication, UserTask userTask) throws Exception {
        Task checkTask = taskDao.queryById(userTask.getTaskId());
        User user = userDao.queryById(Integer.valueOf(authentication.getName()));
        if (userTask.getIsAccomplish() == 1 && (checkTask == null || checkTask.getAccomplishType() == 1)) {
            log.warn("id为 {} 的次级用户试图结束id为 {} 的任务被拒绝", authentication.getName(), userTask.getTaskId());
            throw new TidcBadParent("task不存在或者确认方式不是次级账号确认");
        }
        userTaskDao.finishTask(userTask.getId(), userTask.getIsAccomplish(),userTask.getFilePath());
        if (checkTask.getTypeClassify() == 2) {
            checkTask.setIsDelete(1);
            taskDao.update(checkTask);
        }
        userTask.setUserId(Integer.valueOf(authentication.getName()));
        //获取奖励
        Email email = null;
        RabbitMessageLog experienceLog = null;
        RabbitMessageLog emailLog = null;
        if (userTask.getIsAccomplish() == 1 || userTask.getIsAccomplish() == 3) {
            email = Email.systemAccomplishTaskEmail(user.getName() + "完成了一个任务", user.getName() + "完成了" + checkTask.getName() + "任务", user.getSuperiorUserId());
            experienceLog = RabbitMessageLog.addExperience(objectMapper.writeValueAsString(userTask));
            emailLog = RabbitMessageLog.sendEmail(objectMapper.writeValueAsString(email));

        } else {
            email = Email.systemAccomplishTaskEmail(user.getName() + "放弃了一个任务", user.getName() + "放弃了" + checkTask.getName() + "任务", user.getSuperiorUserId());
            emailLog = RabbitMessageLog.sendEmail(objectMapper.writeValueAsString(email));
            experienceLog = RabbitMessageLog.punishmentExperience(objectMapper.writeValueAsString(userTask));
        }
        rabbitUtil.sendMQ(experienceLog);
        rabbitUtil.sendMQ(emailLog);
        return Fres.Success();
    }

    @Override
    public Fres<Map<Object, Object>> completedTask(int pageSize, int pageNum, int isType, Authentication authentication) throws TidcBadParent {
        int count = userTaskDao.completedTaskCount(Integer.parseInt(authentication.getName()), isType);
        Map<Object, Object> map = SpringUtil.pagingPrepare(pageSize, pageNum, count);
        map.put("list", userTaskDao.completedTask((pageNum - 1) * pageSize, pageSize, isType, Integer.parseInt(authentication.getName())));
        return Fres.Success(map, "成功");
    }

    @Override
    public Fres<Task> getTaskInfo(int id) {
        return Fres.Success(taskDao.queryById(id), "ch");
    }

    /**
     * 判断这个用户是否还能接取这个任务 true为可接
     * 如果是日常任务
     * 手里没有接过 可以接
     * 手里有但是完成时间 在今天之前可以接
     *
     * @param taskType   任务的类型
     * @param createTime 最近一次接取任务的时间
     * @param finishTime 最近一次完成任务的时间
     * @return
     */
    public static boolean checkReceive(int taskType, Timestamp createTime, Timestamp finishTime) throws ParseException {
        SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd");
        String s = sdf.format(new Date());
        boolean flag = false;
        if (taskType == 2 && createTime == null)
            flag = true;
        if (taskType == 1 && createTime == null)
            flag = true;
        if (taskType == 1 && finishTime != null && finishTime.before(sdf.parse(s)))
            flag = true;
        return flag;
    }
}
